package com.okaixz.client.controller;

import com.alibaba.fastjson2.JSON;
import com.okaixz.client.model.domain.User;
import com.okaixz.client.model.dto.UserDto;
import com.okaixz.client.model.dto.WsRequest;
import com.okaixz.client.service.ITokenService;
import com.okaixz.client.service.IUserService;
import com.okaixz.client.service.IWxService;
import com.okaixz.client.service.IXieZuoService;
import com.okaixz.client.utils.SensitiveWordUtil;
import com.okaixz.common.client.WsResult;
import com.okaixz.common.client.exception.BusinessException;
import com.okaixz.common.client.exception.CommonErrorCode;
import com.okaixz.common.client.vo.WxAppPayParams;
import com.okaixz.common.client.vo.WxMiniProgramPayClientReqeust;
import com.okaixz.common.constant.CommonConstants;
import com.okaixz.common.constant.WsRequestCode;
import com.okaixz.common.constant.WsResultCode;
import com.okaixz.common.utils.bean.BeanUtils;
import org.java_websocket.client.WebSocketClient;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket服务
 */
@Component
@ServerEndpoint("/websocket")
//@ServerEndpoint("/websocket/{sid}")
public class WebSocketServer {

    private IWxService wxService;
    private IXieZuoService xieZuoService;
    private ITokenService tokenService;
    private IUserService userService;

    //存放会话对象
    private static Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketServer.applicationContext = applicationContext;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        String id = session.getId();
        System.out.println("客户端：" + id + "建立连接");
        System.out.println("总连接数：" + sessionMap.size());
        sessionMap.put(id, session);
    }

    private WebSocketClient client;

    private static boolean sendData(Session session, WsResult data) {
        boolean result = true;
        try {
            String jsonData = JSON.toJSONString(data);
            System.out.println("websocket发送数据：" + jsonData);
            session.getBasicRemote().sendText(jsonData);
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }

    public static boolean sendData(String sessionId, WsResult data) {
        Session session = sessionMap.get(sessionId);
        if (session == null) {
            System.out.println("websocket发送数据：session为空");
            return false;
        }
        return sendData(session, data);
    }

    public static boolean closeSession(String sessionId) {
        if (!checkToken) {
            return false;
        }
        Session session = sessionMap.get(sessionId);
        if (session == null) {
            return false;
        }
        if (session.isOpen()) {
            try {
                //关闭连接
                session.close();
                System.out.println("连接已经关闭  sessionId=" + sessionId);

                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    // 根据 Session ID 断开特定客户端连接
    public static void disconnectClient(String sessionId) {
        Session session = sessionMap.get(sessionId);
        if (session != null && session.isOpen()) {
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Server shutdown"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static boolean isSessionClose(String sessionId) {
        Session session = sessionMap.get(sessionId);
        if (session == null) {
            return true;
        }
        if (session.isOpen()) {
            return false;
        }
        sessionMap.remove(sessionId);//已经关闭从map中移除
        return true;
    }

    public static boolean checkToken = true;


    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        String sessionId = session.getId();
        sessionMap.put(sessionId, session);
        System.out.println("收到来自客户端：" + sessionId + "的信息:" + message);
        WsRequest request = null;
        try {
            request = JSON.parseObject(message, WsRequest.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (request == null) {
            close(session);
            return;
        }
        Integer requestCode = request.getRequestCode();
        if (requestCode == null) {
            close(session);
            return;
        }
        Integer clientType = request.getClientType();
        if (clientType == null) {
            close(session);
            return;
        }

        //翻译键盘测试修改
        if (clientType == 3) {
            checkToken = false;
        }

        UserDto userDto = null;
        if (checkToken) {
            String token = null;
            if (requestCode != WsRequestCode.GET_QRCODE) {
                //不是获取登录二维码或者 都需要验证token
                token = request.getToken();
                if (token == null) {
                    //token不存在
                    sendData(sessionId, WsResult.error(CommonErrorCode.TOKEN_NULL));
                    close(session);
                    return;
                }
                if (tokenService == null) {
                    tokenService = applicationContext.getBean(ITokenService.class);
                }
                userDto = tokenService.getTokenUser(token);
                if (userDto == null) {
                    //token过期
                    sendData(sessionId, WsResult.error(CommonErrorCode.PARSE_TOKEN_FAIL));
                    close(session);
                    return;
                }
//                userDto = tokenService.refreshUserAndToken(userDto.getUserId());//刷新token
//                //刷新token
//                sendData(sessionId, WsResult.success(userDto, WsResultCode.REFRESH_TOKEN));
            }
        }
        String input = request.getInput();
        boolean contains = SensitiveWordUtil.contains(input);
        if (contains) {
            sendData(sessionId, WsResult.error(CommonErrorCode.SENSITIVE_WORDS));
            return;
        }
        switch (requestCode) {
            case WsRequestCode.GET_QRCODE://登录
                if (wxService == null) {
                    wxService = applicationContext.getBean(IWxService.class);
                }
                if (clientType == 0) {
                    //pc登录
                    String qrcode = wxService.getQrcodeWithParams(sessionId, CommonConstants.WX_QRCODE_TYPE_LOGIN);
                    sendData(session, WsResult.success(qrcode, WsRequestCode.getResultCode(requestCode)));
                }
                break;
            case WsRequestCode.GET_USER_INFO://获取用户信息
                //刷新token
                sendData(sessionId, WsResult.success(userDto, WsRequestCode.getResultCode(requestCode)));
                break;
            case WsRequestCode.SAVE_USER_INFO://保存用户信息
                User user = request.getUser();
                //保存用户信息
                if (userService == null) {
                    userService = applicationContext.getBean(IUserService.class);
                }

                boolean isSuccess = userService.updateUserByUserId(user);
                BeanUtils.copyProperties(user, userDto);
                if (isSuccess) {
                    sendData(sessionId, WsResult.success(userDto, WsRequestCode.getResultCode(requestCode)));
                } else {
                    sendData(sessionId, WsResult.success(userDto, WsResultCode.UPDATE_USER_INFO_FAIL));
                }
                break;
            case WsRequestCode.XIE_ZUO://写作
                if (xieZuoService == null) {
                    xieZuoService = applicationContext.getBean(IXieZuoService.class);
                }
                if (clientType == 2) {
                    //输入法
                    xieZuoService.kbXieZuo(sessionId, request, userDto);
                }
                if (clientType == 3) {
                    //翻译
                    xieZuoService.kbXieZuo(sessionId, request, userDto);
                } else {
                    xieZuoService.xieZuo(sessionId, request, userDto);
                }
                break;
            case WsRequestCode.WX_PAY://微信支付
                if (wxService == null) {
                    wxService = applicationContext.getBean(IWxService.class);
                }
                if (clientType == 0) {
                    //pc端微信扫码支付
                    String payCode = wxService.getWxPayCode(userDto.getUserId(), request.getGid(), sessionId);
                    if (payCode == null) {
                        sendData(session, WsResult.error(CommonErrorCode.PAY_GET_QRCODE_ERROR));
                        return;
                    }
                    sendData(session, WsResult.success(payCode, WsRequestCode.getResultCode(requestCode)));
                } else if (clientType == 1) {
                    //小程序端微信支付
                    WxMiniProgramPayClientReqeust wxMiniProgramPayClientReqeust = wxService.wxMiniProgramCreateOrder(userDto.getUserId(), request.getGid(), sessionId);
                    if (wxMiniProgramPayClientReqeust == null) {
                        sendData(session, WsResult.error(CommonErrorCode.PAY_GET_QRCODE_ERROR));
                        return;
                    }
                    sendData(session, WsResult.success(wxMiniProgramPayClientReqeust, WsRequestCode.getResultCode(requestCode)));
                } else if (clientType == 2) {
                    //言灵键盘app支付
                    WxAppPayParams payParams = wxService.wxAppCreateOrder(userDto.getUserId(), request.getGid(), sessionId);
                    if (payParams == null) {
                        sendData(session, WsResult.error(CommonErrorCode.PAY_GET_QRCODE_ERROR));
                        return;
                    }
                    sendData(session, WsResult.success(payParams, WsRequestCode.getResultCode(requestCode)));
                }
                break;
        }


    }


    private void close(Session session) {
        try {
            session.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 连接关闭调用的方法
     *
     * @param sid
     */
    @OnClose
    public void onClose(Session session, @PathParam("sid") String sid) {
        String sessionId = session.getId();
        System.out.println("===============================================================================连接断开:" + sessionId);
        sessionMap.remove(sessionId);
    }

    /**
     * 群发
     *
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

